Add build option to allow more hypercalls from stubdoms
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 14 Oct 2009 07:54:58 +0000 (08:54 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 14 Oct 2009 07:54:58 +0000 (08:54 +0100)
Stubdoms need to be able to make all the passthrough related
hypercalls on behalf of the guest (for now).

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/Rules.mk
xen/arch/x86/irq.c
xen/arch/x86/physdev.c
xen/common/domctl.c
xen/include/xen/config.h

index 5601e451918a22d1bea7f4298f6c198e3cfb8c56..3f141c33bc97e56e6e23be8c3c34cb07b9ca7147 100644 (file)
@@ -9,6 +9,9 @@ perfc_arrays  ?= n
 crash_debug   ?= n
 frame_pointer ?= n
 
+# Allow some delicate passthrough related hypercalls to be made from a stubdom
+privileged_stubdoms ?= y
+
 XEN_ROOT=$(BASEDIR)/..
 include $(XEN_ROOT)/Config.mk
 
@@ -58,6 +61,10 @@ ifneq ($(max_phys_irqs),)
 CFLAGS-y                += -DMAX_PHYS_IRQS=$(max_phys_irqs)
 endif
 
+ifeq ($(privileged_stubdoms),y)
+CFLAGS += -DPRIVILEGED_STUBDOMS
+endif
+
 AFLAGS-y                += -D__ASSEMBLY__
 
 ALL_OBJS := $(ALL_OBJS-y)
index 2ca28ac28164446968d73a2b2c6141594d50aca0..d4bf176d07498049d9483fa0ebfe766c33bdce09 100644 (file)
@@ -1340,7 +1340,7 @@ int map_domain_pirq(
     ASSERT(spin_is_locked(&pcidevs_lock));
     ASSERT(spin_is_locked(&d->event_lock));
 
-    if ( !IS_PRIV(current->domain) )
+    if ( !STUBDOM_IS_PRIV_FOR(current->domain, d) )
         return -EPERM;
 
     if ( pirq < 0 || pirq >= d->nr_pirqs || irq < 0 || irq >= nr_irqs )
index 474dcf21c34bfb71ae73222b42e0a95e68004788..0c284e84bcdb0c3631b397641cd084e1a909c28d 100644 (file)
@@ -34,9 +34,6 @@ static int physdev_map_pirq(struct physdev_map_pirq *map)
     struct msi_info _msi;
     void *map_data = NULL;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( !map )
         return -EINVAL;
 
@@ -46,8 +43,11 @@ static int physdev_map_pirq(struct physdev_map_pirq *map)
         d = rcu_lock_domain_by_id(map->domid);
 
     if ( d == NULL )
+        return -ESRCH;
+
+    if ( !STUBDOM_IS_PRIV_FOR(current->domain, d) )
     {
-        ret = -ESRCH;
+        ret = -EPERM;
         goto free_domain;
     }
 
@@ -160,9 +160,6 @@ static int physdev_unmap_pirq(struct physdev_unmap_pirq *unmap)
     struct domain *d;
     int ret;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( unmap->domid == DOMID_SELF )
         d = rcu_lock_domain(current->domain);
     else
@@ -171,14 +168,18 @@ static int physdev_unmap_pirq(struct physdev_unmap_pirq *unmap)
     if ( d == NULL )
         return -ESRCH;
 
+    ret = -EPERM;
+    if ( !STUBDOM_IS_PRIV_FOR(current->domain, d) )
+        goto free_domain;
+
     spin_lock(&pcidevs_lock);
     spin_lock(&d->event_lock);
     ret = unmap_domain_pirq(d, unmap->pirq);
     spin_unlock(&d->event_lock);
     spin_unlock(&pcidevs_lock);
 
+free_domain:
     rcu_unlock_domain(d);
-
     return ret;
 }
 
index e21d56593753519f423d444deba75c8593a03e51..60f8e000871c2172e7e7d700b178480ae78c72b5 100644 (file)
@@ -220,15 +220,37 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
     long ret = 0;
     struct xen_domctl curop, *op = &curop;
 
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
     if ( copy_from_guest(op, u_domctl, 1) )
         return -EFAULT;
 
     if ( op->interface_version != XEN_DOMCTL_INTERFACE_VERSION )
         return -EACCES;
 
+    switch ( op->cmd )
+    {
+    case XEN_DOMCTL_ioport_mapping:
+    case XEN_DOMCTL_memory_mapping:
+    case XEN_DOMCTL_bind_pt_irq:
+    case XEN_DOMCTL_unbind_pt_irq:
+    case XEN_DOMCTL_assign_device:
+    case XEN_DOMCTL_deassign_device: {
+        struct domain *d = get_domain_by_id(op->domain);
+        bool_t is_priv = IS_PRIV(current->domain);
+        if ( !is_priv && ((d = rcu_lock_domain_by_id(op->domain)) != NULL) )
+        {
+            is_priv = STUBDOM_IS_PRIV_FOR(current->domain, d);
+            rcu_unlock_domain(d);
+        }
+        if ( !is_priv )
+            return -EPERM;
+        break;
+    }
+    default:
+        if ( !IS_PRIV(current->domain) )
+            return -EPERM;
+        break;
+    }
+
     if ( !domctl_lock_acquire() )
         return hypercall_create_continuation(
             __HYPERVISOR_domctl, "h", u_domctl);
index 7872f13e8d93e88eb3486155aefd1a65bfb63bd0..43d6bc6cff249ec3fa860b3eda381ca16a7410f6 100644 (file)
@@ -95,4 +95,10 @@ int current_domain_id(void);
 #define __cpuinitdata
 #define __cpuinit
 
+#ifdef PRIVILEGED_STUBDOMS
+#define STUBDOM_IS_PRIV_FOR(x,y) IS_PRIV_FOR(x,y)
+#else
+#define STUBDOM_IS_PRIV_FOR(x,y) IS_PRIV(x)
+#endif
+
 #endif /* __XEN_CONFIG_H__ */